package collections;

public class ArrayList<T> implements Collectionable<T>,Iterable<T> {
	public int capacit = 0;
	private int count = 0;
	Object [][] array; 
	public ArrayList(int val){
		array = new Object [Math.round(val/10+0.4f)][10];
		capacit = array.length*10;
	}
	public ArrayList(){
		this(10);
	}
	public void printValues() {
		
    	for (int i=0; i<array.length*10-1; i++) {
    		
        	System.out.print(((array[i/10][i%10]!=null)?array[i/10][i%10]:"null" )+ ", ");
        }
        System.out.println((array[(array.length-1)][9]!=null)?array[(array.length-1)][9]:"null");
    }
	public void printStat(){
		System.out.println("len "+count);
		System.out.println("capacit "+capacit);
		System.out.println("Lenght "+array.length);
	}
	public void increase(int incr){
		Object [][] tmp = new Object [Math.round((float)(capacit+incr)/10f+0.4f)][10];
		for(int i=0;i<=(capacit-1)/10;i++){
			tmp[i] = array[i];
		}
		array=tmp;
		capacit=array.length*10;
//		System.out.println("Array increased");
	}
	public void increase(){
		increase(1);
	}
	public void add(T value){
		if (capacit-count<1){
			increase();
		} 
		array[count/10][count%10]=value;
		count++;
		
	}
	public void insert(T value,int index){
		if (index<capacit && count+1<=capacit) {
			if(array[index/10][index%10] == null){
				array[index/10][index%10]=value;
				count++;
			} 
			else {
				for(int i=capacit-1;i>index;i--){
					array[i/10][i%10]=array[(i-1)/10][(i-1)%10];
				}
				array[index/10][index%10] = null;
				insert(value,index);
			}
		} 
		else {
			increase();
			insert(value,index);
		}
	}
	public void remove(int index){
		if(index<capacit&&array[index/10][index%10]!=null){count--;}
		for(int i=index;i<capacit-1;i++){
			array[i/10][i%10]=array[(i+1)/10][(i+1)%10];
		}
	}
	public void clearAll(){
		array = new Object [capacit/10][10];
	}
	public void shrink(){
		for (int i = 0; i<capacit;i++){
			if (array[i/10][i%10]==null){
				remove(i);
			}			
		}
		for (int i = 0; i<array.length;i++){
			if (array[i][0]==null&&i>0){
				Object [] [] tmp = new Object [i][10];
				for(int j = 0; j<i;j++){
					tmp[j] = array[j];
				}
				array=tmp;
			}			
		}
		capacit = array.length * 10;
	}
	public void shrink(int free){
		shrink();
		if (count+free>capacit){
			increase(count+free-capacit);
		}
	}
	public T elementAt(int index){
		if(array.length>=index%10){
			if(array.length>=index%10){
				return (T) array[index/10][index%10];
			}else return null;
		}else return null;
		
	}
	public Object [][] getClone(){
		return array.clone();
	}
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return count;
	}
	private class Iterator implements Iteratorable<T>,java.util.Iterator<T>{
		private int i=0;
		private T curr;
		@Override
		public boolean moveNext() {
			if (curr == null){
				curr=elementAt(i);
				return (curr == null)?false:true;
			}else{
				if(elementAt(i+1)==null){
					return false;
				}else{
					curr=elementAt(i+1);
					i++;
					return true;
				}
			}
		}

		@Override
		public T getCurrent() {
			return curr;
		}

		@Override
		public boolean hasNext() {
			boolean b= moveNext();
			i--;
			return b;
		}

		@Override
		public T next() {
			// TODO Auto-generated method stub
			
			return moveNext()?getCurrent():null;
		}

		@Override
		public void remove() {
			// TODO Auto-generated method stub
			
		}
		
	}
	@Override
	public Iteratorable<T> getIterator (){
		return new Iterator();
	}
	@Override
	public Collectionable<T> where(Queryable<T> q) {
		ArrayList<T> res = new ArrayList<T>();
		Iteratorable<T> it=this.getIterator();
		while (it.moveNext()){
			if(q.check(it.getCurrent())){
				res.add(it.getCurrent());
			}
		}
		return res;
	}
	@Override
	public java.util.Iterator<T> iterator() {
		// TODO Auto-generated method stub
		return new Iterator();
	}
}
